using System;
using System.Collections.Generic;
using UnityEngine;

public class WaypointPathController : MonoBehaviour
{
	[SerializeField]
	private Waypoint[] _path;

	[SerializeField]
	private bool _isPathLoop;

	[SerializeField]
	private Color _pathColor;

	private Waypoint _previousWaypoint;

	private Waypoint _currentWaypoint;

	private Waypoint _nextWaypoint;

	public Action<WaypointEvent[]> OnWaypointEventTriggered;

	public Action OnLastWaypointReached;

	private void Start()
	{
		for (int i = 0; i < _path.Length; i++)
		{
			Waypoint obj = _path[i];
			obj.OnArrivalCallback = (Action<Waypoint>)Delegate.Combine(obj.OnArrivalCallback, new Action<Waypoint>(ChangeCurrentWaypoint));
			_path[i].Index = i;
		}
	}

	private void ChangeCurrentWaypoint(Waypoint waypoint)
	{
		_previousWaypoint = _currentWaypoint;
		_currentWaypoint = waypoint;
		_nextWaypoint = GetNextWaypoint(waypoint);
		OnWaypointEventTriggered.Fire(waypoint.Events);
		if (_currentWaypoint == GetLastWaypoint())
		{
			OnLastWaypointReached.Fire();
		}
	}

	public Waypoint GetNextWaypoint()
	{
		if (_currentWaypoint == null)
		{
			_nextWaypoint = GetFirstWaypoint();
		}
		return _nextWaypoint;
	}

	private Waypoint GetNextWaypoint(Waypoint waypoint)
	{
		if (IsBetweenPathLimits(waypoint.Index + 1))
		{
			return _path[waypoint.Index + 1];
		}
		if (_isPathLoop)
		{
			return _path[0];
		}
		return null;
	}

	public Waypoint GetCurrentWaypoint()
	{
		return _currentWaypoint;
	}

	public Waypoint GetPreviousWaypoint()
	{
		return _previousWaypoint;
	}

	public Waypoint GetFirstWaypoint()
	{
		return _path[0];
	}

	public Waypoint GetLastWaypoint()
	{
		return _path[_path.Length - 1];
	}

	public float GetDistanceBetweenWaypoints(Waypoint origin, Waypoint destination)
	{
		float num = 0f;
		for (int i = origin.Index; i < _path.Length && i != destination.Index; i++)
		{
			Waypoint nextWaypoint = GetNextWaypoint(_path[i]);
			num += Vector3.Distance(_path[i].GetPosition(), nextWaypoint.GetPosition());
			if (nextWaypoint.Index >= destination.Index)
			{
				return num;
			}
		}
		return num;
	}

	public Waypoint GetNextStopWaypoint(Waypoint origin)
	{
		for (int i = origin.Index; i < _path.Length; i++)
		{
			Waypoint nextWaypoint = GetNextWaypoint(_path[i]);
			if (nextWaypoint.ShouldStop)
			{
				return nextWaypoint;
			}
		}
		return null;
	}

	public List<Waypoint> GetPathUntilNextStopWaypoint(Waypoint origin)
	{
		List<Waypoint> list = new List<Waypoint>();
		if (origin == null)
		{
			origin = GetNextWaypoint();
			list.Add(origin);
			if (origin.ShouldStop)
			{
				return list;
			}
		}
		for (int i = origin.Index; i < _path.Length; i++)
		{
			Waypoint nextWaypoint = GetNextWaypoint(_path[i]);
			list.Add(nextWaypoint);
			if (nextWaypoint == null || nextWaypoint.ShouldStop)
			{
				break;
			}
		}
		return list;
	}

	private bool IsBetweenPathLimits(int index)
	{
		return index >= 0 && index < _path.Length;
	}

	private void OnDrawGizmos()
	{
		Gizmos.color = _pathColor;
		for (int i = 0; i < _path.Length; i++)
		{
			if (i + 1 >= _path.Length)
			{
				if (_isPathLoop)
				{
					Gizmos.DrawLine(_path[i].GetPosition(), _path[0].GetPosition());
				}
			}
			else
			{
				Gizmos.DrawLine(_path[i].GetPosition(), _path[i + 1].GetPosition());
			}
		}
	}

	private void OnDestroy()
	{
		Waypoint[] path = _path;
		foreach (Waypoint waypoint in path)
		{
			Waypoint waypoint2 = waypoint;
			waypoint2.OnArrivalCallback = (Action<Waypoint>)Delegate.Remove(waypoint2.OnArrivalCallback, new Action<Waypoint>(ChangeCurrentWaypoint));
		}
	}
}
